﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Xml.Serialization;

namespace _007_TCPIPClient
{
    class Program
    {
        static ManualResetEvent[] doneEvents;  // Используется для синхронизации с клиентскими потоками
        static void Main(string[] args)
        {
            DateTime current = DateTime.Now;

            Console.WriteLine("Press Enter to start clients");
            Console.ReadLine();
            doneEvents = new ManualResetEvent[10]; // Задаем количество клиентов
            for (int i = 0; i < doneEvents.Length; i++)
            {
                ManualResetEvent evt = doneEvents[i] = new ManualResetEvent(false); // Устанавливаем событие в ожидание

                ThreadPool.QueueUserWorkItem(new WaitCallback((obj) => // Ставим поток в очередь выполнения
                {
                    Client(evt);
                }));
            }

            WaitHandle.WaitAll(doneEvents); // Ждем всех клиентов
            DateTime total = DateTime.Now;
            Console.WriteLine(String.Format("Time : {0} ms", total.Subtract(current).TotalMilliseconds));


            Console.ReadLine();

        }

        public static void Client(ManualResetEvent evt)
        {
            try
            {
                IPEndPoint ipep = new IPEndPoint(IPAddress.Loopback, 9050);
                Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                try
                {
                    server.Connect(ipep); // Подсоединяемся к серверу
                }
                catch (SocketException e)
                {
                    Console.WriteLine("Client: Unable to connect to server.");
                    Console.WriteLine(e.ToString());

                    return;
                }


                try
                {
                    byte[] data = null;
                    int total = 0;
                    IPEndPoint server_point = (IPEndPoint)server.RemoteEndPoint;
                    IPEndPoint server_point_local = (IPEndPoint)server.LocalEndPoint;
                    Console.WriteLine("Client: Connected with {0} at port {1} remote", server_point.Address, server_point.Port);
                    Console.WriteLine("Client: Connected with {0} at port {1} local", server_point_local.Address, server_point_local.Port);

                    int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

                    NetworkStream stream = new NetworkStream(server);
                    XmlSerializer serializer = new XmlSerializer(typeof(int[]));

                    serializer.Serialize(stream, array);
                    stream.Flush();
                    server.Shutdown(SocketShutdown.Send);
                    array = (int[])serializer.Deserialize(stream);

                    for (int i = 0; i < array.Length; i++) Console.WriteLine("Item={0}", array[i]);

                }
                catch (Exception e)
                {
                    Console.WriteLine("Меня игнорируют:" + e.Message);
                }
                Console.WriteLine("Client: Disconnecting from server...");
                server.Shutdown(SocketShutdown.Both);
                server.Close();
            }
            finally
            {
                evt.Set(); //Устанавливаем событие (что бы отследить момент когда все потоки закончаться)
            }
        }
    }
}
